#ifndef _Configuration_H_
#define _Configuration_H_

/**
 Configuration.h
 \file Declaration of class Configuration.
 
 \author Thomas Burton
 \date 11/17/11
 */

#include <iostream>
#include <set>
#include <string>
#include <utility>

#include <Rtypes.h> // For ClassDef

namespace tppmc {
/**
 Holds options configuring how the application runs.
 \todo An option to specify the random seed, in order to be able to
 reproduce specific runs, would be useful.
 \todo Allow selection of centre-of-mass energy as option (replace
 machine type)
 */
class Configuration {
   
public:
   
   /**
    Constructor.
    
    Optionally initialise with command line arguments.
    */
   Configuration(int argc = 0, char* argv[] = NULL);
   
   /**
    Destructor
    */
   virtual ~Configuration();
   
   /**
    Set the configuration from command line arguments.
    Accepts both short options and GNU-style long options.
    Returns the index in argv of the next remaining argument after
    those processed.
    */
   virtual int Set(int argc, char** argv);
   
   /**
    Print the settings of the configuration to an output stream.
    */
   virtual void Speak(std::ostream&) const;
   
   virtual long FragmentationFunction() const { return fftype; }
   virtual long Order() const { return order; }
   virtual int PythiaTune() const { return mPytune; }
   virtual int NEvents() const { return numEvts; }
   virtual bool UseCollinsPositivityBound() const;
   virtual bool UseSiversPositivityBound() const;
   virtual int LhapdfSet() const;
   virtual int LhapdfMember() const;
   virtual bool UseTransversitySofferBound() const;
   virtual int SiversType() const;
   virtual int TransversityType() const;
   virtual double EtaMin() const { return etamin; }
   virtual double EtaMax() const { return etamax; }
   virtual double MeanJt2() const { return mean_jt2; }
   virtual double MinHadronPt() const { return min_hadron_pt; }
   virtual bool GenerateQaFigures() const { return not mQaFiguresFileName.empty(); }
   virtual const std::string& QaFiguresFileName() const { return mQaFiguresFileName; }
   /**
    Returns the hadron species to be used by certain fragmentation functions.
    */
   virtual const std::set<int>& Hadrons() const;
#if 0
   virtual int Acceptance() const;
   virtual const std::string& OutputFileName() const;
   virtual long NEvents() const;
   virtual int MachineType() const;
   virtual int GluonSiversType() const;
   virtual int PythiaEventType() const;
   virtual int OutputMuonArms() const;
   virtual int OutputCentralArms() const;
   virtual int OutputMpc() const;
   virtual int OutputMpcOscar() const;
   virtual int OutputFocal() const;
   virtual int OutputCentralArmPairs() const;
   virtual int OutputMuonArmPairs() const;
   virtual int OutputFocalPairs() const;
   virtual int PrintHelp() const;
#endif
   
   /**
    Verify that all the arguments in the configuration make sense.
    Return true if everything is OK, false if not.
    Non-const as certain values may be modified from input to default
    values if the input values are not valid.
    */
   virtual bool Verify();
   
   virtual void PrintUsage(std::ostream&);
   
   //   protected:
   
   std::string outfile;
   long fftype;
   long order;
   long numEvts;
   int machine_type;
   int pyth_evt_type;
   int quark_transv_soffer;
   int quark_siv_posbnd;
   int sivers_type;
   int transversity_type;
   int fav_pos_bnd;
   int unfav_pos_bnd;
   int helpflag;
   float pyth_parton_pt;
   double etamin;
   double etamax;
   double mean_jt2; // pT between parton and hadron
   double min_hadron_pt;
   double primordial_kt; // Gaussian width of primordial kT distribution
                         // in hadron. Mean kT^2 = width^2.
                         // See PYTHIA 6 PARP(91)
   std::string mQaFiguresFileName;
   std::set<int> mProcesses;
   std::set<int> mHadrons; ///< Hadron species to be generated in fragmentation
   int mPytune;
   std::pair<int, int> mLhapdf; ///< LHAPDF set and member numbers
   long tparticleout;      
   
   ClassDef(tppmc::Configuration, 2)
}; // class Configuration

inline bool Configuration::UseCollinsPositivityBound() const {
   return fav_pos_bnd not_eq 0 or unfav_pos_bnd not_eq 0;
}

inline int Configuration::LhapdfSet() const {
   return mLhapdf.first;
}

inline int Configuration::LhapdfMember() const {
   return mLhapdf.second;
}

inline bool Configuration::UseSiversPositivityBound() const {
   return quark_siv_posbnd not_eq 0;
}

inline bool Configuration::UseTransversitySofferBound() const {
   return quark_transv_soffer not_eq 0;
}

inline int Configuration::SiversType() const {
   return sivers_type;
}

inline int Configuration::TransversityType() const {
   return transversity_type;
}

inline const std::set<int>& Configuration::Hadrons() const {
   return mHadrons;
}

} // namespace tppmc

#endif
